package linc.cool.usage;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author yqlin
 * @date 2021/12/17 1:58 AM
 * @description 两个线程访问同一个对象中的同步方法，同步方法又调用一个非同步方法
 * 两个线程访问同一个对象中的同步方法，同步方法又调用一个非同步方法，仅在没有其他线程直接调用非同步方法的情况下，是线程安全的。
 * 若有其他线程直接调用非同步方法，则是线程不安全的。若有其他线程直接调用非同步方法，则是线程不安全的。
 */
@Slf4j
public class 两个线程访问同一个对象中的同步方法同步方法又调用一个非同步方法 implements Runnable {
    private static final 两个线程访问同一个对象中的同步方法同步方法又调用一个非同步方法 INSTANCE = new 两个线程访问同一个对象中的同步方法同步方法又调用一个非同步方法();

    @Override
    public void run() {
        if ("t0".equals(Thread.currentThread().getName())){
            method();
        }
        syncMethod();
    }

    @SneakyThrows
    private synchronized void syncMethod() {
        log.debug("synchronized {} 执行开始", Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(4);
        method();
        log.debug("synchronized {} 执行结束", Thread.currentThread().getName());
    }

    @SneakyThrows
    private  void method() {
        log.debug(" {} 执行开始", Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(4);
        log.debug(" {} 执行结束", Thread.currentThread().getName());
    }


    @SneakyThrows
    public static void main(String[] args) {
        Thread t0 = new Thread(INSTANCE, "t0");
        Thread t1 = new Thread(INSTANCE, "t1");
        Thread t2 = new Thread(INSTANCE, "t2");
        t0.start();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        t0.join();
        log.debug("end");
    }
}
